package com.five.matebook;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;

import com.five.filesync.MdnsDisovery;

import java.net.InetAddress;
import java.util.HashSet;
import java.util.Set;

public class ServerDiscover implements MdnsDisovery.OnMdnsCallback {
    private static ServerDiscover sInstance;

    public static ServerDiscover getInstance(Context context) {
        if (sInstance == null) {
            synchronized (ServerDiscover.class) {
                if (sInstance == null) {
                    sInstance = new ServerDiscover(context);
                }
            }
        }
        return sInstance;
    }

    private Context context;
    ServerDiscover(Context context) {
        this.context = context;
    }

    private Handler handler = new android.os.Handler(Looper.getMainLooper());
    private Set<MdnsDisovery.OnMdnsCallback> callbackSet = new HashSet<>();

    private MdnsDisovery mdnsDisovery;
    public synchronized void startDiscover(MdnsDisovery.OnMdnsCallback callback) {
        startDiscover(callback, false);
    }
    public synchronized void startDiscover(MdnsDisovery.OnMdnsCallback callback, boolean forceRefresh) {
        if (callback != null) {
            callbackSet.add(callback);
        }

        if (mdnsDisovery != null && !mdnsDisovery.isFinished()) {
            return;
        }

        if (needDiscover(forceRefresh)) {
            cacheTime = 0;
            mdnsDisovery = new MdnsDisovery(context, "five.ftp_server", this);
            mdnsDisovery.setEnable(true);
        } else {
            for (MdnsDisovery.OnMdnsCallback c : callbackSet) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        c.onServiceDiscoverd(cacheAddr, cachePort);
                    }
                });
            }
            callbackSet.clear();
        }
    }

    private boolean needDiscover(boolean force) {
        if (force)  return true;
        return SystemClock.elapsedRealtimeNanos() - cacheTime > 2 * 60 * 1e9;
    }

    private volatile InetAddress cacheAddr;
    private volatile int cachePort;
    private volatile long cacheTime;

    @Override
    public synchronized void onServiceDiscoverd(InetAddress addr, int port) {
        cacheAddr = addr;
        cachePort = port;
        cacheTime = SystemClock.elapsedRealtimeNanos();
        for (MdnsDisovery.OnMdnsCallback callback :callbackSet) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    callback.onServiceDiscoverd(addr, port);
                }
            });
        }
        callbackSet.clear();
    }

    @Override
    public synchronized void onServiceNotFound(String serverName) {
        for (MdnsDisovery.OnMdnsCallback callback :callbackSet) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    callback.onServiceNotFound(serverName);
                }
            });
        }
        callbackSet.clear();
    }
}
